package challengeGUI;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.Timer;

import control.SimpleTimer;

import animation.Animator;
import challengesManager.ChallengeManager;
import elements.GameElement;
import elements.GameElementFactory;

public class FindTheSameGUI extends ChallengeGUI {
	private Timer timer;
	
	private Random random;
	private Animator animator[];
	private GameElement origElements[];
	private GameElement varEle;
	private int active = 0, maxUpdates;
	private boolean paintingAllowed = false, animationOver = false;

	public FindTheSameGUI(ChallengeManager manager) {
		super(manager);
		
		random = new Random(System.currentTimeMillis());
		maxUpdates = 4 + random.nextInt(3);
		
		maxUpdates = 4 + random.nextInt(3);
		animator =  new Animator[2];
		for(int i = 0; i<animator.length; i++) {
			animator[i] = new Animator(this);
			animator[i].setForegroundPainting(true);
		}
		
		timer = new Timer(DEFAULT_UPDATE, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				FindTheSameGUI.this.update();
			}
		});
		timer.setDelay(DEFAULT_UPDATE);
	}
	
	@Override
	public void paint(Graphics g) {
		if(!paintingAllowed) return;
		
		int x = this.getWidth()/2, y = this.getHeight();
		
		for(int i = -1; i<2; ++i) {
			g.setColor(Color.BLACK);
			g.drawLine(x+i, 0, x+i, y);
		}
		
		for(GameElement el : origElements) {
			el.paint(g);
		}
	}
	
	@Override
	public void newRound() {
		for(Animator a : animator) a.clear();
		
		timer.restart();
		
		initialiseElements();
		
		active = 0;
		maxUpdates = 4 + random.nextInt(3);
		animationOver = false;

		// Right Animator
		update();
	}
	
	@Override
	public void freeze() {
		for(Animator ani : animator) ani.stop();
	}
	
	@Override
	public void unfreeze() {
		for(Animator ani : animator) ani.start();
	}
	
	@Override
	public void reveal(final int info) {
		freeze();
		timer.stop();
		
		final Graphics g = this.getGraphics();
		GameElement cloneElements[] = animator[active].getElements();
		
		g.setColor(Color.WHITE);
		g.fillRect(0, 0, this.getWidth(), this.getHeight());
		
		// Doublebuffer
		final BufferedImage img = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_RGB);
		final Graphics tmpG = img.getGraphics();
		
		for(int i = 0; i<20; i++) {
			tmpG.setColor(this.getBackground());
			tmpG.fillRect(0, 0, img.getWidth(), img.getHeight());
			for(int n = 0; n<origElements.length; n++) {
				origElements[n].paint(tmpG);
				cloneElements[n].paint(tmpG);
				
				// New Pos
				cloneElements[n].addX(-myDim.width/40);
			}
			
			// Paints everything
			g.drawImage(img, 0, 0, null);
			
			SimpleTimer.pause(50);
		}

		tmpG.setColor(this.getBackground());
		tmpG.fillRect(0, 0, img.getWidth(), img.getHeight());
		for(int i = 0; i<origElements.length; i++) {
			origElements[i].paint(tmpG);
			cloneElements[i].paint(tmpG);
		}
		// Paints everything
		g.drawImage(img, 0, 0, null);
		
		SimpleTimer.pause(500);
		
		// Fadeout
		final Animator a = new Animator(this);
		for(int i = 0; i<origElements.length; i++) {
			origElements[i].fadeOut(true);
			a.add(origElements[i]);

			// The missing element
			if(varEle == cloneElements[i]) origElements[i].fadeOut(false);
		}
		
		// The different element
		if(varEle != null) {
			a.add(varEle);
		} a.start();

		SimpleTimer.pause(500, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				a.setRightOrWrong(((info==-1)?wrong:right), FindTheSameGUI.this.getWidth()/2, FindTheSameGUI.this.getHeight()/2);
			}
		});
		
		a.setRightOrWrong(((info==-1)?wrong:right), this.getWidth()/2, this.getHeight()/2);
		SimpleTimer.pause(2500, new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				a.stop();
				g.setColor(FindTheSameGUI.this.getBackground());
				g.fillRect(0, 0, img.getWidth(), img.getHeight());
				
				for(Animator ani : animator) ani.clear();
				
				manager.animationOver();
			}
		});

//		g.setColor(this.getBackground());
//		g.fillRect(0, 0, img.getWidth(), img.getHeight());
//		
//		for(Animator ani : animator) ani.clear();
	}
	
	@Override
	public void end() {
		for(Animator ani : animator) ani.stop();
	}
	
	public void update() {
		// Clears the old animator
		animator[active].stop();
		animator[active].clear();
		
		// Switches to the next Animator
		active = (active+1) % animator.length;
		
		// Initialises the Animator
		int var = random.nextInt(origElements.length);
		Animator a = animator[active];

		boolean buzzMoment = true;
		// Variates one element
		varEle = null;
		for(int i = 0; i<origElements.length; i++) {
			if(random.nextInt(4) != 0 && i == var && maxUpdates > 0) {
				varEle = Animator.factory.newRandomElement(GameElement.NO_MOVEMENT,
						scaler,
						GameElementFactory.withoutChar);
				varEle.setRandomColor();
				varEle.setRandomPosition(myDim.width, myDim.height);
				// Sets the XPos on the right side
				varEle.setX(myDim.width/2 + random.nextInt(myDim.width/2 - varEle.getWidth()));
				a.add(varEle);
				
				// Manager
				buzzMoment = false;
			} else {
				try {
					GameElement el;
					el = origElements[i].clone();
					el.addX(myDim.width/2);
					a.add(el);
				} catch (CloneNotSupportedException e) {
					// Sollte nicht passieren
				}
			}
		}
		
		manager.perfectBuzzMoment(buzzMoment);
		
		// Shows the Elements
		a.start();

		--maxUpdates;

		// Manager
		if(buzzMoment) animationOver = true;
		if(animationOver && maxUpdates <= 0) manager.animationOver();
	}
	
	private void initialiseElements() {
		// Just a reference
		GameElementFactory fac = Animator.factory;
		
		origElements = new GameElement[4 + random.nextInt(4)];
		// Adds random Elements
		for(int i = 0; i<origElements.length; i++) {
			origElements[i] = fac.newRandomElement(GameElement.NO_MOVEMENT,
					scaler,
					GameElementFactory.withoutChar);
			origElements[i].setRandomPosition(myDim.width/2, myDim.height);
			origElements[i].setRandomColor();
		}
		
		if(!paintingAllowed) paintingAllowed = true;
	}
}